home *** CD-ROM | disk | FTP | other *** search
/ PC Media 22 / PC MEDIA CD22.iso / share / prog / datalib2 / database.cpp next >
C/C++ Source or Header  |  1995-08-15  |  6KB  |  300 lines

  1. #include "datapriv.hpp"
  2.  
  3. /*************** DATABASE ACCESSOR FUNCTIONS ***************/
  4.  
  5. // Get pointer to index by name, return 0 if not found
  6.  
  7. index *database::getindex(char *name)
  8. {
  9.  if (!findex) return 0;
  10.  
  11.  index *ip=findex;
  12.  while(ip && strcmpl(ip->name,name)) ip=ip->next;
  13.  
  14.  return ip;
  15. }
  16.  
  17. char *database::getindkey(char *name)
  18. {
  19.  index *ip;
  20.  
  21.  if (ip=getindex(name)) return(ip->indexp);
  22.  return 0;
  23. }
  24.  
  25. int database::getindtype(char *name)
  26. {
  27.  index *ip;
  28.  
  29.  if (ip=getindex(name)) return(ip->indtype);
  30.  return 0;
  31. }
  32.  
  33. /*************** DATABASE FUNCTIONS ************************/
  34.  
  35.  
  36. // This is the constructor for a database
  37. // it opens the file and initialises the database variables.
  38.  
  39. /*************** CONSTRUCTOR *******************************/
  40.  
  41.  
  42. // This is the constructor for a new database
  43.  
  44. database::database()
  45. {
  46.  valid=-1;
  47.  ex=0;
  48.  exwork=0;
  49.  dbtp=0;
  50.  memowl=0;
  51.  memow=0;
  52.  firstrec=0;
  53.  change=1;
  54.  findex=0;
  55.  dbfp=0;
  56.  nrec=0;
  57.  nfield=0;
  58.  maxfieldl=0;
  59.  reclen=1;
  60.  findex=0;
  61.  dateformat=USDATE;
  62.  if (!(fielda=new field*[MAXFLD])) {dbfer(NODBSP); valid=NOMEM;}
  63. }
  64.  
  65. // This is the constructor for an existing database
  66.  
  67. database::database(char *name,char *index)
  68. {
  69.  char n[128],ws[128],*wsp;
  70.  int i;
  71.  int recpos=1;
  72.  
  73.  valid=0;
  74.  ex=0;            // Start with no expression evaluator
  75.  exwork=0;
  76.  dbtp=0;
  77.  memowl=0;
  78.  memow=0;
  79.  firstrec=0;
  80.  change=0;
  81.  findex=0;
  82.  dateformat=USDATE;
  83.  if (!(fielda=new field*[MAXFLD])) {dbfer(NODBSP); valid=NOMEM; return;}
  84.  
  85.  
  86.  strcpy(n,name);
  87.  if (!strchr(n,'.')) strcat(n,".dbf");
  88.  
  89.  if (!(dbfp=fopen(n,"r+b"))) {valid=NOFILE; return;}
  90.  
  91.  Fread(ws,DBSIZE,1,dbfp);          // Get database file statistics
  92.  
  93.  if (*ws&0x80)
  94.  {
  95.   *(strchr(n,'.'))=0; strcat(n,".dbt");
  96.   dbtp=fopen(n,"r+b");
  97.   if (!dbtp) {valid=MEMOERR; return;}
  98.  }
  99.  nrec=*(long *)(ws+4);                // Now get the file parameters
  100.  recstart=*(int *)(ws+8);
  101.  reclen=*(int *)(ws+10);
  102.  
  103.  nfield=0; maxfieldl=0;
  104.  
  105.  do    // Count number of fields
  106.  {
  107.   fielda[nfield]=0;
  108.   Fread(ws,DBSIZE,1,dbfp);
  109.   if (*ws==0x0d) break;
  110.   nfield++;
  111.  }
  112.  while(!feof(dbfp));
  113.  
  114.  Fseek(dbfp,0L,SEEK_SET);
  115.  Fread(ws,DBSIZE,1,dbfp);
  116.  
  117.  for(i=0; i<nfield; i++)                    // Read all field information
  118.  {
  119.   int flen;             // Field length
  120.  
  121.   Fread(ws,DBSIZE,1,dbfp);
  122.   flen=(unsigned char)ws[16];
  123.   if (!(fielda[i]=new field(i+1,ws,ws[11],flen,
  124.            (unsigned char)ws[17],recpos)))
  125.     {dbfer(NODBSP); valid=NOMEM; return;}
  126.   recpos=recpos+flen;
  127.   if (flen>maxfieldl) maxfieldl=flen;
  128.  }
  129.                // Now open the index file
  130.  
  131.  if (!index || !(*index)) return;
  132.  valid=addindex(index);
  133. }
  134.  
  135. /*************** DESTRUCTOR ********************************/
  136.  
  137. // This is the destructor for a database object.
  138.  
  139. database::~database(void)
  140. {
  141.  int i;
  142.  class field *temp;
  143.  
  144.  if (dbfp)
  145.  {
  146.   if (change)
  147.   {
  148.    struct tm *t;
  149.    time_t ltime;
  150.  
  151.    time(<ime); t=localtime(<ime);
  152.    Fseek(dbfp,1L,SEEK_SET);
  153.    Fputc(t->tm_year,dbfp);
  154.    Fputc(t->tm_mon+1,dbfp);
  155.    Fputc(t->tm_mday,dbfp);
  156.    fputl(nrec,dbfp);
  157.   }
  158.   fclose(dbfp);
  159.   for(i=0; i<nfield; i++) if (fielda[i]) delete fielda[i];
  160.  }
  161.  
  162.  index *ip=findex;
  163.  index *nip;
  164.  while(ip) {nip=ip; ip=ip->next; delete nip;}    // Close all the indexes
  165.  
  166.  if (fielda) delete fielda;
  167.  if (ex) delete ex;
  168.  if (exwork) delete exwork;
  169.  if (memow) delete memow;
  170.  if (dbtp) fclose(dbtp);
  171.  if (firstrec) dber(DELREC);    // Cannot delete database with attached rec.s
  172. }
  173.  
  174. /*************** GETFIELD *******************************/
  175.  
  176.  
  177. // This function searches for a field by name and returns a pointer
  178.  
  179. field *database::getfield(char *fname)
  180. {
  181.  for (int i=0; i<nfield; i++)
  182.  {
  183.   if (!strcmpl(fielda[i]->name,fname)) return(fielda[i]);
  184.  }
  185.  
  186.  return(0);
  187. }
  188.  
  189. /*************** Add a field to a fresh database ********/
  190.  
  191. // This version copies a field from elsewhere
  192.  
  193. int database::addfield(field *fp)
  194. {
  195.  if (valid>=0) return INVFIELD;
  196.  
  197.  int i;
  198.  
  199.  for(i=0; i<nfield; i++)
  200.   if (!strcmpi(fielda[i]->name,fp->name)) return DUPFIELD;
  201.  
  202.  nfield++;
  203.  fielda[nfield-1]=new field(nfield,fp->name,fp->type,fp->len,fp->rdp,reclen);
  204.  reclen+=fp->len;
  205.  if (fp->len>maxfieldl) maxfieldl=fp->len;
  206.  if (fp->type) valid=-2;
  207.  return 0;
  208. }
  209.  
  210.  
  211. // This version adds a completely new field
  212.  
  213. int database::addfield(char *name,int type,int len,int rdp)
  214. {
  215.  if (valid>=0) return INVFIELD;
  216.  
  217.  int i;
  218.  
  219.  for(i=0; i<nfield; i++)
  220.   if (!strcmpi(fielda[i]->name,name)) return DUPFIELD;
  221.  
  222.  int ln=len;
  223.  if (ln<1) return INVFIELD;
  224.  switch(type&0xdf)
  225.  {
  226.   case 'C'    : break;
  227.   case 'D'    : ln=8; break;
  228.   case 'L'    : ln=1; break;
  229.   case 'M'    : valid=-2; ln=10; break;
  230.   case 'N'    : if (rdp<0 || rdp>len-2) return INVFIELD; break;
  231.   default    : return INVFIELD;
  232.  }
  233.  
  234.  nfield++;
  235.  fielda[nfield-1]=new field(nfield,name,type,ln,rdp,reclen);
  236.  reclen+=ln;
  237.  if (ln>maxfieldl) maxfieldl=ln;
  238.  return 0;
  239. }
  240.  
  241. /*************** Write a database to disk ****************/
  242.  
  243. int database::write(char *name)
  244. {
  245.  if (valid>=0 || !nfield) return NOFILE;
  246.  
  247.  char n[128],ws[512],*wsp;
  248.  int i;
  249.  
  250.  strcpy(n,name); if (!strchr(n,'.')) strcat(n,".dbf");
  251.  if (!(dbfp=fopen(n,"w+b"))) {valid=NOFILE; return NOFILE;}
  252.  
  253.  if (valid==-2)
  254.  {
  255.   *(strchr(n,'.'))=0; strcat(n,".dbt");
  256.   dbtp=fopen(n,"w+b");
  257.   if (!dbtp) {valid=MEMOERR; return MEMOERR;}
  258.   memset(ws,0,512);
  259.   *ws=1;
  260.   sprintf(ws+16,"Memo File written by dBase Library, Robin Abbott, %s",name);
  261.   Fwrite(ws,512,1,dbtp);
  262.  }
  263.  
  264.  memset(ws,0,32);
  265.  *ws=(dbtp) ? 0x83 : 0x03;
  266.  recstart=32*(nfield+1)+1;
  267.  *(int *)(ws+8)=recstart;
  268.  *(int *)(ws+10)=reclen;
  269.  Fwrite(ws,32,1,dbfp);
  270.  
  271.  for(i=0; i<nfield; i++)
  272.  {
  273.   memset(ws,0,32);
  274.   strcpy(ws,fielda[i]->name);
  275.   ws[11]=fielda[i]->type;
  276.   ws[16]=fielda[i]->len;
  277.   ws[17]=fielda[i]->rdp;
  278.   Fwrite(ws,32,1,dbfp);
  279.  }
  280.  Fputc(0x0d,dbfp);
  281.  
  282.  valid=0;
  283.  return 0;
  284. }
  285.  
  286. /*****************************************
  287.  
  288. Here come a number of utility routines
  289.  
  290. ******************************************/
  291.  
  292.  
  293. void fputl(long l,FILE *fp)
  294. {
  295.  fputc(l&0xff,fp);
  296.  fputc((l>>8) & 0xff,fp);
  297.  fputc((l>>16) & 0xff,fp);
  298.  fputc((l>>24) & 0xff,fp);
  299. }
  300.